package org.mm4juser.service.serviceImpl;

import jakarta.annotation.Resource;
import org.mm4juser.entity.DTO.*;
import org.mm4juser.entity.User;
import org.mm4juser.repository.UserRepository;
import org.mm4juser.service.UserService;
import org.mm4juser.util.JWTTokenUtil;
import org.mm4juser.util.RedisTokenUtil;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;

import static org.mm4juser.util.ValidateFileTypeUtil.validateFileType;

@Service
public class UserServiceImpl implements UserService {
	@Resource
	UserRepository userRepository;
	
	/**
	 * 根据邮箱地址加载用户信息
	 *
	 * @param email 用户的邮箱地址，用于查询用户信息
	 *
	 * @return 返回一个ResponseEntity对象，包含查询到的用户信息，HTTP状态码为200(OK)
	 */
	@Override
	public ResponseEntity<?> loadUser(String email) {
		// 使用userRepository通过邮箱地址查询用户信息，并返回HTTP 200状态码和查询结果
		return ResponseEntity.ok(userRepository.loadUserByEmail(email));
	}
	
	/**
	 * 登录方法实现
	 *
	 * @param loginDTO 包含登录信息的DTO对象
	 *
	 * @return 返回包含登录结果和用户信息的DTO对象
	 */
	@Override
	public LoginDTO login(
		LoginDTO loginDTO
		// 登录数据传输对象，包含用户邮箱、密码等信息
	) {
		// 通过邮箱查询用户信息并对比
		User user = userRepository.loadUserByEmail(loginDTO.getUser()
			                                           .getEmail());    // 根据邮箱从数据库查询用户信息
		if (user != null) {    // 判断用户是否存在
			if (user.getPassword()
				.equals(loginDTO.getUser()
					        .getPassword())) {    // 比对用户输入的密码与数据库中存储的密码是否一致
				// 生成token
				String token = JWTTokenUtil.getToken(
					user.getEmail());    // 使用JWT工具类生成登录令牌
				// 保存token
				if (RedisTokenUtil.getToken(user.getEmail()) != null) {    // 检查Redis中是否已存在该用户的token
					if (RedisTokenUtil.getToken(user.getEmail())
						.equals(token)) {    // 比较新生成的token与Redis中存储的token是否相同
						RedisTokenUtil.removeToken(user.getEmail());    // 如果token相同，则移除旧的token
					}
				}
				RedisTokenUtil.saveToken(    // 将新生成的token保存到Redis中
				                             user.getEmail(),
				                             token,
				                             loginDTO.getRemember());    // remember参数用于控制token的有效期
				loginDTO.setUser(user);    // 将查询到的用户信息设置到DTO中
				// 将Token传入客户端方便客户端保存到本地
				loginDTO.setToken(token);    // 将生成的token设置到DTO中
				loginDTO.setMessage("登录成功");    // 设置登录成功消息
				// 若邮箱对应账号不为空且密码比对正确，则返回查询到的用户所有信息
				return loginDTO;    // 返回包含用户信息和token的DTO
			}
			// 用户存在但密码错误
			loginDTO.setMessage("密码错误");    // 设置密码错误消息
			return loginDTO;    // 返回包含错误消息的DTO
		}
		// 用户不存在
		loginDTO.setMessage("用户不存在");    // 设置用户不存在消息
		return loginDTO;    // 返回包含错误消息的DTO
	}
	
	/**
	 * 用户注册（用户名、邮箱、密码）
	 *
	 * @param user 用户实体
	 *
	 * @return 注册成功\注册失败，服务器出错\注册失败，邮箱已占用
	 */
	@Override
	public ResponseEntity<?> register(User user) {
		// 查询邮箱是否被占用
		if (userRepository.loadUserByEmail(user.getEmail()) == null) {
			// 包含用户名、邮箱、密码
			user.createUUID();
			if (userRepository.createUser(user) == 1) {
				// 返回1条变动
				return ResponseEntity.ok("注册成功");
			}
			// 返回0条变动
			return ResponseEntity.internalServerError()
				.body("注册失败，服务器出错");
		}
		return ResponseEntity.internalServerError()
			.body("注册失败，邮箱已占用");
	}
	
	/**
	 * 退出登录
	 *
	 * @param user 用户实体
	 *
	 * @return 退出成功、服务器出错，退出失败
	 */
	@Override
	public ResponseEntity<?> exit(User user) {
		String result = RedisTokenUtil.removeToken(user.getEmail());
		if (result == null) {//用户退出登录时，移除其在服务器的token
			return ResponseEntity.ok("退出成功");
		} else {
			return ResponseEntity.internalServerError()
				.body("服务器出错，退出失败");
		}
	}
	
	/**
	 * 忘记&修改密码
	 *
	 * @param pwdChangeDTO DTO对象（邮箱、旧密码、新密码）
	 *
	 * @return 用户不存在、修改成功、旧密码错误
	 */
	@Override
	public ResponseEntity<?> forgetOrChangePwd(PwdChangeDTO pwdChangeDTO) {
		// 查询是否存在该用户
		User user = userRepository.loadUserByEmail(pwdChangeDTO.getEmail());
		if (user == null) {
			return ResponseEntity.badRequest()
				.body("用户不存在");
		} else if (user.getPassword()
			.equals(pwdChangeDTO.getOldPwd())) {
			user.setPassword(pwdChangeDTO.getNewPwd());
			userRepository.updateUser(user);
			exit(user);//修改成功后退出
			return ResponseEntity.ok("修改成功，请重新登录！");
		} else {
			return ResponseEntity.badRequest()
				.body("旧密码错误");
		}
		
	}
	
	/**
	 * 修改用户主要属性
	 *
	 * @param mainInfoChangeDTO DTO对象（User、新邮箱、新用户名）
	 *
	 * @return 该邮箱已被占用、修改成功、资料未修改
	 */
	@Override
	public ResponseEntity<?> changeMainInfo(MainInfoChangeDTO mainInfoChangeDTO) {
		// 如果新邮箱被填写，则说明用户修改的是邮箱
		if (mainInfoChangeDTO.getNewEmail() != null) {
			if (userRepository.loadUserByEmail(mainInfoChangeDTO.getNewEmail()) != null) {
				return ResponseEntity.internalServerError()
					.body("该邮箱已被占用");
			} else {
				exit(mainInfoChangeDTO.getUser());
				mainInfoChangeDTO.getUser()
					.setEmail(mainInfoChangeDTO.getNewEmail());
				userRepository.updateUser(mainInfoChangeDTO.getUser());//退出并修改邮箱
				return ResponseEntity.ok("修改成功，请重新登录！");
			}
		}
		// 说明用户修改的是用户名
		if (mainInfoChangeDTO.getNewUsername() != null) {
			mainInfoChangeDTO.getUser()
				.setUsername(mainInfoChangeDTO.getNewUsername());
			userRepository.updateUser(mainInfoChangeDTO.getUser());
			return ResponseEntity.ok(userRepository.loadUserByEmail(mainInfoChangeDTO.getUser()
				                                                        .getEmail()));//若修改成功，则返回新的User信息
		}
		return ResponseEntity.ok("资料未修改");
	}
	
	/**
	 * 修改用户次要属性
	 *
	 * @param secondInfoChangeDTO DTO对象（User、新个签、新性别、新生日）
	 *
	 * @return 资料未修改、修改成功
	 */
	@Override
	public ResponseEntity<?> changeSecondInfo(SecondInfoChangeDTO secondInfoChangeDTO) {
		//如果三个次要资料都未修改则判定为资料未修改
		if (secondInfoChangeDTO.getNewBirthday()
			    .equals(secondInfoChangeDTO.getUser()
				            .getBirthday()) && secondInfoChangeDTO.getNewGender() == secondInfoChangeDTO.getUser()
			.getGender() && secondInfoChangeDTO.getNewSignature()
			    .equals(secondInfoChangeDTO.getUser()
				            .getSignature())) {
			return ResponseEntity.ok("资料未修改");
		} else {
			//只要有一个改动就判定为修改
			secondInfoChangeDTO.getUser()
				.setBirthday(secondInfoChangeDTO.getNewBirthday());
			secondInfoChangeDTO.getUser()
				.setGender(secondInfoChangeDTO.getNewGender());
			secondInfoChangeDTO.getUser()
				.setSignature(secondInfoChangeDTO.getNewSignature());
			userRepository.updateUser(secondInfoChangeDTO.getUser());
			return ResponseEntity.ok("修改成功");
		}
	}
	
	/**
	 * 头像上传方法 用于处理用户头像上传、文件校验、保存及数据库更新的完整流程
	 *
	 * @param avatarChangeDTO DTO对象（User、新头像）
	 *
	 * @return 上传成功、上传失败的响应实体
	 */
	public ResponseEntity<?> changeAvatar(AvatarChangeDTO avatarChangeDTO) throws IOException {
		// 参数校验
		if (avatarChangeDTO == null || avatarChangeDTO.getNewAvatar() == null ||
		    avatarChangeDTO.getNewAvatar()
			    .isEmpty()) {
			return ResponseEntity.badRequest()
				.body("文件不能为空");
		}
		
		// 文件类型和大小校验
		String originalFilename = avatarChangeDTO.getNewAvatar()
			.getOriginalFilename();
		if (! validateFileType(avatarChangeDTO.getNewAvatar())) {
			return ResponseEntity.badRequest()
				.body("不支持的文件类型");
		}
		if (avatarChangeDTO.getNewAvatar()
			    .getSize() > 5 * 1024 * 1024) {
			return ResponseEntity.badRequest()
				.body("文件大小不能超过5MB");
		}
		
		try {
			// 构建保存路径
			String baseDir = System.getProperty("user.dir") + File.separator + "data" + File.separator + "img" + File.separator + "userAvatar";
			String fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
			String newFileName = UUID.randomUUID() + fileExtension;
			
			// 确保目录存在
			Path savePath = Paths.get(baseDir);
			if (! Files.exists(savePath)) {
				Files.createDirectories(savePath);
			}
			
			// 保存文件
			Path filePath = savePath.resolve(newFileName);
			avatarChangeDTO.getNewAvatar()
				.transferTo(filePath.toFile());
			
			// 更新数据库
			String avatarPath = filePath.toString()
				.replace(
					"\\",
					"/");
			
			int result = userRepository.updateUserAvatar(
				avatarPath,
				avatarChangeDTO.getEmail());
			
			return result == 1 ?
				ResponseEntity.ok("上传成功") :
				ResponseEntity.internalServerError()
					.body("上传失败");
			
		}
		catch (IOException e) {
			return ResponseEntity.internalServerError()
				.body("文件上传失败");
		}
	}
}
